package com.ikun.common.fIlter;

import com.ikun.common.constant.RedisConstant;
import com.ikun.common.manager.RedisManager;
import com.ikun.common.result.Result;
import com.ikun.common.utils.HttpContextUtils;
import com.ikun.common.utils.ResponseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @ClassName LimitFilter
 * @Description: 限流过滤器
 * @CreateDate: 2024/4/11 16:49
 */
public class LimitFilter implements HandlerInterceptor, Ordered {
    private Logger logger = LoggerFactory.getLogger(LimitFilter.class);
    @Autowired
    private RedisManager redisManager;

    @Override
    public int getOrder() {
        return 1;
    }

    /**
     * 拦截处理
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("进入限流接口");
        String ipAddr = HttpContextUtils.getIpAddr(request);
        //基于滑动窗口的限流模式
        long currentTime = System.currentTimeMillis();

        Long oneMinuteAgo = currentTime - RedisConstant.ONE_MINUTE;
        Long oneHourAgo = currentTime - RedisConstant.ONE_HOUR;
        Long oneDayAgo = currentTime - RedisConstant.ONE_DAY;

        String key = RedisConstant.LIMIT_SET_PREFIX + ipAddr;
        //获取一分钟之内的登录次数
        long oneMinuteTimes = redisManager.countZSetByScore(key, oneMinuteAgo, currentTime);
        if (oneMinuteTimes >= RedisConstant.ONE_MINUTE_TIMES) {
            //超出限制 加入黑名单
            logger.info("限流不通过~");
            redisManager.addList(RedisConstant.BLACK_SET, ipAddr);
            ResponseUtils.sendResponse(response,new Result<String>().success("访问太频繁了，请稍候再来"));
            return false;
        }
        long oneHourTimes = redisManager.countZSetByScore(key,oneHourAgo,currentTime);
        if(oneHourTimes>= RedisConstant.ONE_HOUR_TIMES){
            logger.info("限流不通过~~");
            redisManager.addList(RedisConstant.BLACK_SET, ipAddr);
            ResponseUtils.sendResponse(response,new Result<String>().success("访问太频繁了，请一小时再来"));
            return false;
        }

        long oneDayTimes = redisManager.countZSetByScore(key,oneDayAgo,currentTime);
        if(oneDayTimes>= RedisConstant.ONE_DAY_TIMES){
            logger.info("限流不通过~~~");
            redisManager.addList(RedisConstant.BLACK_SET, ipAddr);
            ResponseUtils.sendResponse(response,new Result<String>().success("访问太频繁了，请一天后再来"));
            return false;
        }
        logger.info("限流通过");
        redisManager.addZSet(key,currentTime,UUID.randomUUID().toString());
        return true;
    }


}
